/**
 * @license
 * Copyright 2021 Du Tian Wei
 * SPDX-License-Identifier: Apache-2.0
 */

import * as obvm from '../../runtime/vm.mjs'
import * as obcanvaslib from './canvas.mjs'
import * as oblib_network from './network.mjs'
import * as util from '../../runtime/util.mjs'

let logDiv = document.getElementById('logDiv');
let logs = [];
/**
 * @type {HTMLCanvasElement}
 */
let stage = document.getElementById("stage");

stage.height = parseInt(window.getComputedStyle(stage).height) * 2;
stage.width = parseInt(window.getComputedStyle(stage).width) * 2;
let obcanvas = new obcanvaslib.OBCanvas2D(stage);
let nativeLibs = [obcanvas.install.bind(obcanvas), oblib_network.OBNetwork.install];
var scriptArrayBuffer;
// var phaserSceneJSONStr;
let loadedScript, assets;
let vm;
let fsm;
function v2(e) {
    let t = e.currentTarget;
    let height = t.height;
    let width = t.width;
    let x = e.clientX;
    let y = e.clientY;
    let swidth = t.getBoundingClientRect().width;
    let sheight = t.getBoundingClientRect().height;
    let sx = x / swidth * width;
    let sy = y / sheight * height;
    sx = Math.floor(sx);
    sy = Math.floor(sy);
    return new obcanvaslib.Vector2(sx, sy);
}
function ob_event(name, argType, arg) {
    if (vm) {
        vm.BroadcastMessage(new obvm.OBEventMessage(name, argType, arg, null));
    }
}
stage.addEventListener('touchstart', (e) => {
    ob_event('touchstart', 'Vector2', v2(e));
}, false);
stage.addEventListener('mousedown', (e) => {
    ob_event('touchstart', 'Vector2', v2(e));
}, false);
stage.addEventListener('touchmove', (e) => { ob_event('touchmove', 'Vector2', v2(e)) }, false);
stage.addEventListener('touchcancel', (e) => { ob_event('touchcancel', 'Vector2', v2(e)) }, false);
stage.addEventListener('touchend', (e) => { ob_event('touchend', 'Vector2', v2(e)) }, false);
stage.addEventListener('mouseup', (e) => { ob_event('touchend', 'Vector2', v2(e)) }, false);
stage.addEventListener('click', (e) => { ob_event('click', 'Vector2', v2(e)) }, false);
stage.addEventListener('longpress', (e) => { ob_event('longpress', 'Vector2', v2(e)) }, false);
stage.addEventListener('swipe', () => { ob_event('swipe') }, false);
document.addEventListener('keydown', (e) => {
    ob_event('keydown', 'String', e.key)
}, false);
document.addEventListener('keyup', (e) => {
    ob_event('keyup', 'String', e.key)
}, false);
const inputElement = document.getElementById("input_script");
inputElement.addEventListener("change", () => {
    const fileList = inputElement.files;
    if (fileList.length == 0) {
        return;
    }
    let reader = new FileReader();
    reader.onload = (evt) => {
        stage.width = stage.width;
        scriptArrayBuffer = reader.result;
        loadedScript = obvm.OBScriptLoader.loadScript(scriptArrayBuffer, nativeLibs);
    };
    reader.readAsArrayBuffer(fileList[0]);
}, false);

const runButton = document.getElementById('button_run');
function restart(_fsm) {
    if (vm) {
        vm = null;
    }
    obcanvas.canvas2dctx.restore();
    if (loadedScript) {
        obcanvas.canvas2dctx.save();
        vm = new obvm.OBVM(loadedScript, {
            setTimeout: setTimeout.bind(window), Output: debugLog,
            assets: assets || {}
        });
        // vm.Output = alert.bind(window);
        let fsmname = _fsm || document.getElementById("input_start_fsm").value;
        fsm = vm.CreateFSM(fsmname);
        if (!fsm) {
            debugLog("No FSM named " + fsmname);
        }
    }
}
runButton.onclick = ()=>{restart()};

function step() {
    window.requestAnimationFrame(step);
    if (vm) {
        vm.update();
    }
}
window.requestAnimationFrame(step);
function debugLog(m) {
    console.log(m);
    logs.unshift(String(m));
    if (logs.length > 15) {
        logs.length = 15;
    }
    logDiv.innerText = logs.join('\n');
}
if (window.parent) {
    let messageHandler = {
        runProject(evt) {
            stage.width = stage.width;
            scriptArrayBuffer = evt.data.bytes;
            loadedScript = obvm.OBScriptLoader.loadScript(scriptArrayBuffer, nativeLibs);
            assets = {};
            let _assets = evt.data.assets;
            let finished = 0;
            let wait = 0;
            for (let name in _assets) {
                let imgsuffixs = ['.png', '.jpg', '.jpeg'];
                for (let suffixs in imgsuffixs) {
                    if (name.endsWith(imgsuffixs[suffixs])) {
                        wait++;
                        let img = new Image();
                        let base64 = util.arrayBufferToBase64(_assets[name]);
                        let fileType = util.fileType(name).substring(1);
                        img.src = 'data:image/' + fileType + ';base64,' + base64;
                        img.onload = () => {
                            finished++;
                            if (finished == wait) {
                                restart(evt.data.fsm);
                            }
                        };
                        img.onerror = () => {
                            finished++;
                            if (finished == wait) {
                                restart(evt.data.fsm);
                            }
                        };
                        assets[name] = img;
                    }
                }
            }
            if (finished == wait) {
                restart(evt.data.fsm);
            }
        },
        restart(evt) {
            restart(evt.data.fsm);
        }
    };
    window.addEventListener("message", receiveMessage);

    function receiveMessage(event) {
        let cmd = event.data.cmd;
        if (messageHandler[cmd]) {
            messageHandler[cmd](event);
        }
    }

    ; (function () {
        var throttle = function (type, name, obj) {
            obj = obj || window;
            var running = false;
            var func = function () {
                if (running) { return; }
                running = true;
                requestAnimationFrame(function () {
                    obj.dispatchEvent(new CustomEvent(name));
                    running = false;
                });
            };
            obj.addEventListener(type, func);
        };

        /* init - you can init any event */
        throttle("resize", "optimizedResize");
    })();

    // handle event
    window.addEventListener("optimizedResize", function () {
        let styled = window.getComputedStyle(stage);
        stage.height = parseInt(styled.height) * 2;
        // stage.width = parseInt(styled.width) * 2;
        // restart();
        ob_event('windowResize', 'null');
    });

}